package compoundDB.database;

import compoundDB.core.*;
import compoundDB.database.container.*;
import compoundDB.database.enumeration.*;

import java.sql.SQLException;
import java.util.List;

/**
 * This interface specifies the method calls the core will be able to make to
 * interact with the database, to retrieve or enter compounds.
 * 
 * @author Kohl Bromwich
 * 
 */
public interface DatabaseAccessor
{
	/**
	 * This method allows for the addition of a column field to the database. It
	 * will be added immediately, and open QueryReaders will need to be renewed
	 * with a new search in order to make use of the new column. Reccomended to
	 * close all QueryReaders before calling this.
	 * 
	 * @param name
	 *            The name of the new column to add.
	 * 
	 * @param type
	 *            The type of data the column should store.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with database, or
	 *             duplicate column name is used (expected).
	 */
	void addColumnField(String name, DataType type) throws SQLException;
	
	/**
	 * This method provides the ability to quickly add compounds in bulk, using
	 * a transaction. If an error occurs (exception is thrown) while adding them
	 * all, then none will be added.
	 * 
	 * @param compounds
	 *            The list of new compounds to be added to the database. GUID of
	 *            compounds must be zero!
	 * 
	 * @throws SQLException
	 *             when error occurs communicating with database, or duplicate
	 *             entry is found (expected).
	 */
	void addCompounds(List<Compound> compounds) throws SQLException;
	
	/**
	 * This method will return a list of names from the index, with the names
	 * starting with the contents of mess, returning maxNum names at max, or
	 * else as many as are found (may return an empty list).
	 * 
	 * @param mess
	 *            The string to complete.
	 * 
	 * @param maxNum
	 *            The maximum (and preferred) number of autocomplete results to
	 *            be returned.
	 * 
	 * @return The list of strings completed from teh given string.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with the database.
	 */
	List<String> autoCompleteName(String mess, int maxNum) throws SQLException;
	
	/**
	 * This method closes the connection to the database and cleans up any
	 * associated internal components.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with database.
	 */
	void closeDatabaseConnection() throws SQLException;
	
	/**
	 * This method removes a compound from the database. All properties and
	 * names will be deleted.
	 * 
	 * @param guids
	 *            The list of GUIDs of the compounds to delete.
	 * 
	 * @throws SQLException
	 *             when error occurs communicating with database.
	 */
	void deleteCompound(List<Long> guids) throws SQLException;
	
	/**
	 * This method will return a list of compounds from the database specified
	 * by guids in the list.
	 * 
	 * @param guids
	 *            The list of Globally Unique IDentifiers to specify the
	 *            compounds to be retrieved from the database.
	 * 
	 * @return A QueryReader which will extract compounds from the ResultSet.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with the database.
	 */
	QueryReader getCompounds(List<Long> guids) throws SQLException;
	
	/**
	 * This method will return a list of compounds from the database with names
	 * starting with the string given.
	 * 
	 * @param name
	 *            The name of the compound to be retrieved from the database.
	 * 
	 * @return A QueryReader which will extract compounds from the ResultSet.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with the database.
	 */
	QueryReader getCompounds(String name) throws SQLException;
	
	/**
	 * This method returns a list of the columns in the database table, and
	 * hence what data is stored for compounds.
	 * 
	 * @return The list of ColumnFields defining what compound
	 *         properties/columns exist in the database.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with database.
	 */
	List<ColumnField> getCompoundTableColumns() throws SQLException;
	
	/**
	 * This method retrieves the extra names a compound has from the database.
	 * 
	 * @param guid
	 *            The Globally Unique IDentifier of the molecule to retrieve
	 *            names for.
	 * 
	 * @return The list of names for the compound retrieved from the database.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with the database.
	 */
	List<String> getNames(long guid) throws SQLException;
	
	/**
	 * This method opens the connection to the database and sets up any required
	 * internal components.
	 * 
	 * @throws SQLException
	 *             if an error occurs connecting to the database.
	 */
	void openDatabaseConnection() throws SQLException;
	
	/**
	 * This method allows for the removal of an existing column field in the
	 * database. It will be removed immediately, but the column will still exist
	 * in already open QueryReaders. Reccomended to close all QueryReaders
	 * before calling this.
	 * 
	 * @param column
	 *            The ColumnField column to remove from the database.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with database, or if a
	 *             ColumnField is given that is not in the database.
	 */
	void removeColumnField(ColumnField column) throws SQLException;
	
	/**
	 * This method allows a column field in the database to be renamed. It will
	 * be renamed immediately, but the name will not be changed in QueryReaders
	 * already open. Reccomended to close all QueryReaders before calling this.
	 * 
	 * @param column
	 *            The ColumnField column to rename.
	 * 
	 * @param newName
	 *            The name to change the column to.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with database, or if a
	 *             ColumnField is given that is not in the database, or if the
	 *             new name is a duplicate (expected).
	 */
	void renameColumnField(ColumnField column, String newName)
			throws SQLException;
	
	/**
	 * This method will return a QueryReader after performing an SQL query in
	 * the database, making a search based on the search parameters given in
	 * searchValues. Each string will be and'ed.
	 * 
	 * @param searchValues
	 *            The list of search filters to be applied to the search.
	 * 
	 * @return A QueryReader which will extract compounds from the ResultSet.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with the database, or when
	 *             bad search options are given (for example when a ColumnField
	 *             that doesn't exist in the database is used).
	 */
	QueryReader searchCompounds(List<SearchOption> searchValues)
			throws SQLException;
	
	/**
	 * This method will update the given compound in the database. Exception
	 * will be thrown if the compound guid does not exist in the database.
	 * 
	 * @param compound
	 *            The modified compound to update in the database.
	 * 
	 * @throws SQLException
	 *             when an error occurs communicating with the database, or if
	 *             the compound guid does not exist in the database (expected).
	 */
	void updateCompound(Compound compound) throws SQLException;
}
